package com.xiyu.service.service.office;

import com.xiyu.service.vo.office.space.SpaceGetGroupTypeInfoOutput;
import com.xiyu.service.enums.office.space.OfficeSpaceStatusEnum;
import com.xiyu.service.vo.office.space.SpaceSingleGetOutput;
import com.xiyu.service.model.office.space.OfficeSpaceWorker;
import com.xiyu.service.repository.office.space.OfficeSpaceWorkerRepository;
import com.xiyu.service.vo.office.space.SpaceUpdateInput;
import com.xiyu.service.model.office.space.OfficeSpaceProps;
import com.xiyu.service.model.office.space.OfficeSpaceDraft;
import com.xiyu.service.vo.office.space.SpaceCreateInput;
import com.xiyu.service.model.office.space.OfficeSpace;
import com.xiyu.service.repository.office.space.OfficeSpaceRepository;
import com.xiyu.service.vo.office.space.SpacePageQueryOutput;
import com.xiyu.service.vo.office.space.SpacePageQueryInput;
import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import org.springframework.validation.annotation.Validated;
import org.babyfish.jimmer.Page;
import java.util.*;

import org.springframework.transaction.annotation.Transactional;
import com.xiyu.service.util.entity.EntityUtils;
import org.babyfish.jimmer.DraftObjects;
import com.xiyu.service.framework.web.web.core.pojo.PageResult;
import com.xiyu.service.convert.office.SpaceConvert;

import static com.xiyu.service.framework.exception.util.ServiceExceptionUtil.exception;
import static com.xiyu.service.errorCode.office.SpaceErrorCode.*;

/**
 * 办公用房管理 Service 实现类
 */
@Service
@Validated
public class SpaceServiceImpl implements SpaceService {

    @Resource
    private OfficeSpaceWorkerRepository officeSpaceWorkerRepository;

    @Resource
    private OfficeSpaceRepository officeSpaceRepository;




    @Override
    public PageResult<SpacePageQueryOutput> pageQuery(SpacePageQueryInput inputVO) {
        Page<OfficeSpace> pageOfficeSpace = officeSpaceRepository.pageQuery(inputVO);
        List<SpacePageQueryOutput> listOfficeSpace = SpaceConvert.INSTANCE.pageQueryOutputConvert(pageOfficeSpace.getRows());
        return new PageResult<>(listOfficeSpace, pageOfficeSpace.getTotalRowCount());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long create(SpaceCreateInput inputVO) {
        OfficeSpace newOfficeSpace = SpaceConvert.INSTANCE.createInputConvert(inputVO);
        if(!inputVO.getSpaceWorkers().isEmpty()){
            newOfficeSpace = OfficeSpaceDraft.$.produce(newOfficeSpace, draft -> {
                draft.setStatus(OfficeSpaceStatusEnum.USED.getValue());
            });
        }
        newOfficeSpace = officeSpaceRepository.insert(newOfficeSpace);
        return newOfficeSpace.id();

    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean update(SpaceUpdateInput inputVO) {
        Optional<OfficeSpace> optionalOldOfficeSpace = officeSpaceRepository.findById(inputVO.getId());
        if(!optionalOldOfficeSpace.isPresent()){
            throw exception(OFFICE_SPACE_NOT_EXIST);
        }
        for(SpaceUpdateInput.spaceWorker worker : inputVO.getSpaceWorkers()){
            if(Objects.equals(worker.getOperateType(), "delete")){
                Optional<OfficeSpaceWorker> optionalDeleteOfficeSpaceWorker = officeSpaceWorkerRepository.findById(worker.getId());
                if(!optionalDeleteOfficeSpaceWorker.isPresent()){
                    throw exception(OFFICE_SPACE_WORKER_NOT_EXIST);
                }
                officeSpaceWorkerRepository.deleteById(worker.getId());
            }else if(Objects.equals(worker.getOperateType(), "new")){
                Optional<OfficeSpaceWorker> optionalDuplicateOfficeSpaceWorker = officeSpaceWorkerRepository.findFirstBySpaceIdAndWorkerId(worker.getSpaceId(), worker.getWorkerId());
                if(optionalDuplicateOfficeSpaceWorker.isPresent()){
                    throw exception(OFFICE_SPACE_WORKER_DUPLICATE);
                }
                OfficeSpaceWorker newOfficeSpaceWorker = SpaceConvert.INSTANCE.updateInputConvert(worker);
                officeSpaceWorkerRepository.insert(newOfficeSpaceWorker);
            }else{
                Optional<OfficeSpaceWorker> optionalOldOfficeSpaceWorker = officeSpaceWorkerRepository.findById(worker.getId());
                if(!optionalOldOfficeSpaceWorker.isPresent()) {
                    throw exception(OFFICE_SPACE_WORKER_NOT_EXIST);
                }
                Optional<OfficeSpaceWorker> optionalDuplicateOfficeSpaceWorker = officeSpaceWorkerRepository.findFirstBySpaceIdAndWorkerId(worker.getSpaceId(), worker.getWorkerId());
                if(optionalDuplicateOfficeSpaceWorker.isPresent() && !worker.getId().equals(optionalDuplicateOfficeSpaceWorker.get().id())){
                    throw exception(OFFICE_SPACE_WORKER_DUPLICATE);
                }
                OfficeSpaceWorker updateOfficeSpaceWorker = SpaceConvert.INSTANCE.updateInputConvert(worker);
                if (!EntityUtils.isEquals(optionalOldOfficeSpaceWorker.get(), updateOfficeSpaceWorker))
                    officeSpaceWorkerRepository.update(updateOfficeSpaceWorker);
            }
        }

        List<OfficeSpaceWorker> spaceWorkers = officeSpaceWorkerRepository.findBySpaceId(inputVO.getId());
        OfficeSpace updateOfficeSpace = SpaceConvert.INSTANCE.updateInputConvert(inputVO);
        updateOfficeSpace = OfficeSpaceDraft.$.produce(updateOfficeSpace, draft -> {
            DraftObjects.unload(draft, OfficeSpaceProps.SPACE_WORKERS);
            draft.setStatus(spaceWorkers.isEmpty() ? OfficeSpaceStatusEnum.EMPTY.getValue() : OfficeSpaceStatusEnum.USED.getValue());
        });
        if (!EntityUtils.isEquals(optionalOldOfficeSpace.get(), updateOfficeSpace))
            officeSpaceRepository.update(updateOfficeSpace);
        return true;
    }

    @Override
    public SpaceSingleGetOutput singleGet(Long id) {
        Optional<OfficeSpace> optionOfficeSpace = officeSpaceRepository.findDetailById(id);
        if(!optionOfficeSpace.isPresent()){
            throw exception(OFFICE_SPACE_NOT_EXIST);
        }
        return SpaceConvert.INSTANCE.singleGetOutputConvert(optionOfficeSpace.get());

    }

    @Override
    public List<SpaceGetGroupTypeInfoOutput> getGroupTypeInfo() {
        return SpaceConvert.INSTANCE.getGroupTypeInfoOutputConvert(officeSpaceRepository.findGroupTypeInfo());
    }

}
